<?php

namespace component\element\multifile\controller;

use app\bll\UserGrade as BllUserGrade;
use core\component\ElementBase;
use core\traits\ElementView as TraitsElementView;
use app\bll\SyscnfUpload as BllSyscnfUpload;

class Index extends ElementBase
{

    public function index(...$param)
    {


        //获取会员等级
        $bllBllUserGrade = new BllUserGrade();
        $usergrades = $bllBllUserGrade->select();


        return $this->view(array_merge(
            $param,
            ['usergrades' => $usergrades]
        ));
    }


    /**
     * 上传
     *
     * @param [String] $path 要上传的文件夹
     * @param [String] $tmppath 临时文件夹
     * @return void
     */
    public function upload()
    {

        $plugin = request()->elementinfo['plugin'] == '' ? 'frame'
            : request()->elementinfo['plugin'];

        $uploadfloder = $plugin;


        $targetDir = public_path() . '/upload/' . $uploadfloder . '/temp/';  //存放临时文件夹
        $uploadDir = public_path() . '/upload/' . $uploadfloder . '/';     //实际上传的文件夹

        $cleanupTargetDir = true;      // Remove old files
        $maxFileAge       = 5 * 3600;  //Temp file age in seconds
        // Create target dir
        if (!file_exists($targetDir)) {
            @mkdir($targetDir, 0777, true);
        }

        // Create target dir
        if (!file_exists($uploadDir)) {
            @mkdir($uploadDir, 0777, true);
        }

        $uploadfile = request()->file();
        $fileName = request()->file()['file']->getUploadName();

        //检查后缀名
        $extension         = request()->file()['file']->getUploadExtension();
        $bllRcSyscnfUpload = new BllSyscnfUpload();
        $uploadcnf         = $bllRcSyscnfUpload->find();
        $exts              = explode(',', $uploadcnf['attachext']);
        if (!in_array('.' . $extension, $exts)) {
            return json_encode([
                'jsonrpc' => '2.0',
                'error'   => [
                    'code'    => 100,
                    'message' => "该格式不允许上传",
                ]
            ]);
        }


        $filePath   = $targetDir . DIRECTORY_SEPARATOR . $fileName;
        $uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;

        // Chunking might be enabled
        $chunk  = request()->input('chunk', 0);
        $chunks = request()->input('chunks', 1);


        // Remove old temp files

        if ($cleanupTargetDir) {
            if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
                return json_encode([
                    'jsonrpc' => '2.0',
                    'error'   => [
                        'code'    => 100,
                        'message' => "Failed to open temp directory.",
                    ]
                ]);
            }

            while (($file = readdir($dir)) !== false) {
                $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;

                if ($tmpfilePath == $filePath . "_" . $chunk . ".part" || $tmpfilePath == $filePath . "_" . $chunk . ".parttmp") {
                    continue;
                }


                if (preg_match('/\.(part|parttmp)$/', $file) && (@filemtime($tmpfilePath) < time() - $maxFileAge)) {
                    @unlink($tmpfilePath);
                }
            }
            closedir($dir);
        }


        // Open temp file
        if (!$out = @fopen($filePath . '_' . $chunk . ".parttmp", "wb")) {
            return json_encode([
                'jsonrpc' => '2.0',
                'error'   => [
                    'code'    => 102,
                    'message' => "Failed to open output stream.",
                ]
            ]);
        }

        if (!empty($uploadfile)) {

            if ($uploadfile['file']->getUploadErrorCode()) {
                return json_encode([
                    'jsonrpc' => '2.0',
                    'error'   => [
                        'code'    => 103,
                        'message' => "Failed to move uploaded file.",
                    ]
                ]);
            }

            // Read binary input stream and append it to temp file

            if (!$in = @fopen($uploadfile['file']->getRealPath(), "rb")) {
                return json_encode([
                    'jsonrpc' => '2.0',
                    'error'   => [
                        'code'    => 101,
                        'message' => "Failed to open input stream.",
                    ]
                ]);
            }
        } else {


            if (!$in = @fopen(request()->rawBody(), "rb")) {

                return json_encode([
                    'jsonrpc' => '2.0',
                    'error'   => [
                        'code'    => 101,
                        'message' => "Failed to open input stream.",
                    ]
                ]);
            }
        }

        while ($buff = fread($in, 4096)) {
            fwrite($out, $buff);
        }

        @fclose($out);
        @fclose($in);

        rename($filePath . "_" . $chunk . ".parttmp", $filePath . '_' . $chunk . ".part");

        $index = 0;
        $done  = true;
        for ($index = 0; $index < $chunks; $index++) {
            if (!file_exists($filePath . '_' . $index . ".part")) {
                $done = false;
                break;
            }
        }
        if ($done) {
            if (!$out = @fopen($uploadPath, "wb")) {
                return [
                    'jsonrpc' => '2.0',
                    'error'   => [
                        'code'    => 102,
                        'message' => "Failed to open output stream.",
                    ]
                ];
            }

            if (flock($out, LOCK_EX)) {
                for ($index = 0; $index < $chunks; $index++) {
                    if (!$in = @fopen($filePath . "_" . $index . ".part", "rb")) {
                        break;
                    }

                    while ($buff = fread($in, 4096)) {
                        fwrite($out, $buff);
                    }

                    @fclose($in);
                    @unlink($filePath . "_" . $index . ".part");
                }

                flock($out, LOCK_UN);
            }
            @fclose($out);
            // Return Success JSON-RPC response
            $size = filesize($uploadDir . '/' . $fileName);
            return json_encode([
                'jsonrpc' => '2.0',
                'path'    => '/upload/' . $uploadfloder . '/' . $fileName,
                'size'    => format_bytes($size)
            ]);
        }
    }
}
